package main

import (
	"context"
	"flag"
	"fmt"
	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"io"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	"cloudnative/module10/metrics"
	//注入性能分析
	_ "net/http/pprof"
)

/**
1.接收客户端 request，并将 request 中带的 header 写入 response header
2.读取当前系统的环境变量中的 VERSION 配置，并写入 response header
3.Server 端记录访问日志包括客户端 IP，HTTP 返回码，输出到 server 端的标准输出
4.当访问 localhost/healthz 时，应返回200
*/

func main() {

	flag.Set("v", "4")
	flag.Set("logtostderr", "true")
	flag.Parse()

	glog.V(4).Info("My WebServer Starting ...")
	//注册指标
	metrics.Register()

	mux := http.NewServeMux()

	mux.HandleFunc("/", defaultHandler)
	mux.HandleFunc("/delay", delayHandler)
	mux.HandleFunc("/healthz", healthHandler)
	mux.Handle("/metrics", promhttp.Handler())

	srv := http.Server{
		Addr:    ":8899",
		Handler: mux,
	}

	done := make(chan os.Signal, 1)
	//优雅退出
	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		//监听8899
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			glog.Fatalf("listen: %s\n", err)
		}
	}()
	glog.V(4).Info("中文 My WebServer Started")
	<-done
	glog.V(4).Info("My WebServer Stopped")

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer func() {
		// extra handling here
		glog.Flush()
		cancel()
	}()

	if err := srv.Shutdown(ctx); err != nil {
		glog.Fatalf("Server Shutdown Failed:%+v", err)
	}
	glog.V(4).Info("Server Exited Properly")

}

func writeHeader(resp http.ResponseWriter, header http.Header) {
	version := os.Getenv("VERSION")
	glog.V(4).Infof("version=%s", version)
	if version != "" {
		resp.Header().Set("VERSION", version)
	}

	for k, v := range header {
		for _, single := range v {
			if strings.Contains(k, "X-") {
				//保留traceid头
				resp.Header()[strings.ToLower(k)] = []string{single}
			} else {
				resp.Header().Set(k, single)
			}

		}
	}

}

func defaultHandler(resp http.ResponseWriter, req *http.Request) {
	if req.RequestURI == "/favicon.ico" {
		return
	}

	defer func() {
		err := recover()
		if err != nil {
			glog.V(4).Infof("statsCode=%d", http.StatusInternalServerError)
			resp.WriteHeader(http.StatusInternalServerError)
		} else {
			glog.V(4).Infof("statsCode=%d", http.StatusOK)
			resp.WriteHeader(http.StatusOK)
		}

	}()

	glog.V(4).Info("defaultHandler")
	glog.V(4).Infof("remoteAddr=%s", req.Host)
	writeHeader(resp, req.Header)

	//panic("xxx")
	resp.Write([]byte("success:" + strconv.FormatInt(time.Now().UnixMilli(), 10)))

}

func healthHandler(resp http.ResponseWriter, req *http.Request) {
	glog.V(4).Info("healthHandler")
	resp.Write([]byte("up"))
	resp.WriteHeader(200)
}

func randInt(min int, max int) int {
	rand.Seed(time.Now().UTC().UnixNano())
	return min + rand.Intn(max-min)
}

func delayHandler(resp http.ResponseWriter, req *http.Request) {
	glog.V(4).Info("entering delayHandler")
	timer := metrics.NewTimer()
	defer timer.ObserveTotal()
	user := req.URL.Query().Get("user")
	//添加 0-2 秒的随机延时
	delay := randInt(0, 2000)
	time.Sleep(time.Millisecond * time.Duration(delay))
	if user != "" {
		io.WriteString(resp, fmt.Sprintf("hello [%s]\n", user))
	} else {
		io.WriteString(resp, "hello [stranger]\n")
	}
	io.WriteString(resp, "===================Details of the http request header:============\n")
	for k, v := range req.Header {
		if strings.Contains(k, "X-") {
			//保留traceid头
			io.WriteString(resp, fmt.Sprintf("%s=%s\n", strings.ToLower(k), v))
		} else {
			io.WriteString(resp, fmt.Sprintf("%s=%s\n", k, v))
		}

	}
	glog.V(4).Infof("Respond in %d ms", delay)
}
